/*
* Copyright (c) 2020 The canvas Authors. All rights reserved.
  Use of this source code is governed by a BSD-style license that can be
  found in the LICENSE file.

* Author:         dzlua - https://gitee.com/dzlua/canvas.git
* Email:          505544956@qq.com
* FileName:       render.h
* Create Time:    2020/01/05 10:38:43
* Description:    /
*/

#ifndef __CANVAS_D2D_IMPL_H__
#define __CANVAS_D2D_IMPL_H__

#include <canvas_impl.h>
#include <canvas_2d_impl.h>

#include <d2d1.h>
#include <dwrite.h>
#include <wincodec.h>

#include <vector>

#define CVS_S_RenderBrushAlreadyExist       CVS_S_RenderInternal +1

#define CVS_E_RenderSurfaceError            CVS_E_RenderInternal -1
#define CVS_E_RenderPathError               CVS_E_RenderInternal -2
#define CVS_E_RenderShapeError              CVS_E_RenderInternal -3
#define CVS_E_RenderPathNotOpen             CVS_E_RenderInternal -4
#define CVS_E_RenderNoTarget                CVS_E_RenderInternal -5
#define CVS_E_RenderNoBrush                 CVS_E_RenderInternal -6
#define CVS_E_RenderErrorShapeType          CVS_E_RenderInternal -7
#define CVS_E_ShapeNotSupportDraw           CVS_E_RenderInternal -8
#define CVS_E_ShapeNotSupportFill           CVS_E_RenderInternal -9
#define CVS_E_BitmapBrushNotSetBiamtp       CVS_E_RenderInternal -10

namespace cvs {
namespace c2d {
  class D2DRender;
  class D2DTarget;
  class D2DSurface;
  class D2DBitmapTarget;

  class CustomTextRender : public IDWriteTextRenderer {
    protected:
      friend class D2DRender;
      CustomTextRender(ID2D1Factory *d2d_factory);
      virtual ~CustomTextRender();
      void reset();
      HRESULT transGeometry(ID2D1Geometry *geometry
          , FLOAT baselineOriginX, FLOAT baselineOriginY
          , ID2D1TransformedGeometry **transformed_geometry);
    public:
      void SetEnv(FLOAT dpi, const D2D1_MATRIX_3X2_F &matrix);
      HRESULT BeginDraw();
      HRESULT EndDraw();
      HRESULT Geometry(std::vector<ID2D1TransformedGeometry*> *texts
          , std::vector<ID2D1TransformedGeometry*> *underlines
          , std::vector<ID2D1TransformedGeometry*> *strikethroughs) const;
    public:
      STDMETHOD(DrawGlyphRun)(
          __maybenull void* clientDrawingContext,
          FLOAT baselineOriginX,
          FLOAT baselineOriginY,
          DWRITE_MEASURING_MODE measuringMode,
          __in DWRITE_GLYPH_RUN const* glyphRun,
          __in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
          __maybenull IUnknown* clientDrawingEffect
          ) override;
      STDMETHOD(DrawUnderline)(
          __maybenull void* clientDrawingContext,
          FLOAT baselineOriginX,
          FLOAT baselineOriginY,
          __in DWRITE_UNDERLINE const* underline,
          __maybenull IUnknown* clientDrawingEffect
          ) override;
      STDMETHOD(DrawStrikethrough)(
          __maybenull void* clientDrawingContext,
          FLOAT baselineOriginX,
          FLOAT baselineOriginY,
          __in DWRITE_STRIKETHROUGH const* strikethrough,
          __maybenull IUnknown* clientDrawingEffect
          ) override;
      STDMETHOD(DrawInlineObject)(
          __maybenull void* clientDrawingContext,
          FLOAT originX,
          FLOAT originY,
          IDWriteInlineObject* inlineObject,
          BOOL isSideways,
          BOOL isRightToLeft,
          __maybenull IUnknown* clientDrawingEffect
          ) override;

      STDMETHOD(IsPixelSnappingDisabled)(
          __maybenull void* clientDrawingContext,
          __out BOOL* isDisabled
          ) override;
      STDMETHOD(GetCurrentTransform)(
          __maybenull void* clientDrawingContext,
          __out DWRITE_MATRIX* transform
          ) override;
      STDMETHOD(GetPixelsPerDip)(
          __maybenull void* clientDrawingContext,
          __out FLOAT* pixelsPerDip
          ) override;

      virtual HRESULT STDMETHODCALLTYPE QueryInterface( 
          /* [in] */ REFIID riid,
          /* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject) override;
      virtual ULONG STDMETHODCALLTYPE AddRef( void) override;
      virtual ULONG STDMETHODCALLTYPE Release( void) override;
    protected:
      ULONG ref_count_;
      ID2D1Factory *d2d_factory_;
      D2D1_MATRIX_3X2_F matrix_;
      FLOAT dpi_;
      std::vector<ID2D1TransformedGeometry*> texts_;
      std::vector<ID2D1TransformedGeometry*> underlines_;
      std::vector<ID2D1TransformedGeometry*> strikethroughs_;
  };
} // end namespace c2d
} // end namespace cvs

namespace cvs {
namespace c2d {
  class D2DResource : public Base, virtual public IResource {
    public:
      virtual IRender* render() const override;
    public:
      D2DRender* d2d_render() const;
      IFactory* factory() const;
      ID2D1Factory* d2d_factory() const;
      IDWriteFactory* dwrite_factory() const;
      CustomTextRender* text_render() const;
    protected:
      D2DResource(D2DRender *render);
      virtual ~D2DResource();
    protected:
      D2DRender *render_;
  };

  class D2DTargetResource : public D2DResource, virtual public ITargetResource {
    public:
      virtual ITarget* target() const override;
    public:
      ID2D1RenderTarget* d2d_target() const;
    protected:
      D2DTargetResource(D2DRender *render, D2DTarget *target);
      virtual ~D2DTargetResource();
    protected:
      D2DTarget *target_;
  };

  class D2DSurfaceData : public D2DResource, virtual public ISurfaceData {
    public:
      virtual Result reset() override;
      virtual Size size() const override;
      virtual uint stride() const override;
      virtual Result pixels(uint *buffer_size, void **data) const override;
    protected:
      Result create(IWICBitmap *bitmap);
    protected:
      friend class D2DSurface;
      D2DSurfaceData(D2DRender *render);
      virtual ~D2DSurfaceData();
    protected:
      IWICBitmapLock *wic_lock_;
  };
  class D2DSurface : public D2DResource, virtual public ISurface {
    public:
      virtual Result reset() override;
      virtual Result create(const PixelFormat format, const Size &size) override;
      virtual Result load_file(const char *file) override;
      virtual Result load_buffer(const char *buffer, ulong size) override;
      virtual Result save(const char *file, SurfaceType type) const override;

      virtual Size size() const override;
      virtual PixelFormat format() const override;
      virtual uint buffer_size() const override;
      virtual Result copy_pixels(uint stride, uint buffer_size, void *pixels) const override;
      virtual Result data(ISurfaceData **surface_data) override;
    public:
      IWICBitmap* wic_bitmap() const;
      REFWICPixelFormatGUID wic_pixel_format(PixelFormat format) const;
      GUID wic_container_format(SurfaceType type) const;
    protected:
      IWICImagingFactory* create_wic_factory() const;
      Result create_wic_bitmap(IWICImagingFactory *factory, IWICBitmapSource *source);
    protected:
      friend class D2DRender;
      friend class D2DSurfaceTarget;
      D2DSurface(D2DRender *render);
      virtual ~D2DSurface();
    protected:
      IWICBitmap *wic_bitmap_;
  };

  class D2DShape : public D2DResource {
    public:
      virtual Result fill(ID2D1RenderTarget *target, ID2D1Brush *brush) const;
      virtual Result draw(ID2D1RenderTarget *target, ID2D1Brush *brush, dtype stroke_width, ID2D1StrokeStyle *style) const;
    protected:
      friend class D2DRender;
      D2DShape(D2DRender *render);
      virtual ~D2DShape();
  };
  class D2DShapeBaseForUsePath : public D2DShape {
    public:
      virtual Result reset() override;
      virtual Result fill(ID2D1RenderTarget *target, ID2D1Brush *brush) const override;
      virtual Result draw(ID2D1RenderTarget *target, ID2D1Brush *brush, dtype stroke_width, ID2D1StrokeStyle *style) const override;
    protected:
      virtual void d2d_path_paint(ID2D1GeometrySink *sink) const = 0;
    protected:
      friend class D2DRender;
      D2DShapeBaseForUsePath(D2DRender *render);
      virtual ~D2DShapeBaseForUsePath();
    protected:
      virtual Result generate_d2d_path_geometry();
    protected:
      ID2D1PathGeometry *d2d_path_;
  };
  class D2DShapeLine : public ShapeLine, public D2DShape {
    public:
      virtual Result draw(ID2D1RenderTarget *target, ID2D1Brush *brush, dtype stroke_width, ID2D1StrokeStyle *style) const override;
    protected:
      friend class D2DRender;
      D2DShapeLine(D2DRender *render);
      virtual ~D2DShapeLine();
  };
  class D2DShapePolyline : public ShapePolyline, public D2DShape {
    public:
      virtual Result draw(ID2D1RenderTarget *target, ID2D1Brush *brush, dtype stroke_width, ID2D1StrokeStyle *style) const override;
    protected:
      friend class D2DRender;
      D2DShapePolyline(D2DRender *render);
      virtual ~D2DShapePolyline();
  };
  class D2DShapeBezier : public ShapeBezier, public D2DShapeBaseForUsePath {
    public:
      virtual Result reset() override;
      virtual Result set(const BezierSegment &beizer) override;
      virtual Result set(const Point &pt0, const Point &pt1, const Point &pt2, const Point &pt3) override;
    protected:
      virtual void d2d_path_paint(ID2D1GeometrySink *sink) const override;
    protected:
      friend class D2DRender;
      D2DShapeBezier(D2DRender *render);
      virtual ~D2DShapeBezier();
  };
  class D2DShapeArc : public ShapeArc, public D2DShapeBaseForUsePath {
    public:
      virtual Result reset() override;
      virtual Result set(const ArcSegment &arc) override;
      virtual Result set(const Point &start, const Point &end, const Size &size, dtype angle, bool sweep, bool large) override;
    protected:
      virtual void d2d_path_paint(ID2D1GeometrySink *sink) const override;
    protected:
      friend class D2DRender;
      D2DShapeArc(D2DRender *render);
      virtual ~D2DShapeArc();
  };
  class D2DShapePolygon : public ShapePolygon, public D2DShapeBaseForUsePath {
    public:
      virtual Result reset() override;
      virtual Result set(const Point *pts, uint count) override;
    protected:
      virtual void d2d_path_paint(ID2D1GeometrySink *sink) const override;
    protected:
      friend class D2DRender;
      D2DShapePolygon(D2DRender *render);
      virtual ~D2DShapePolygon();
  };
  class D2DShapeRect : public ShapeRect, public D2DShape {
    public:
      virtual Result fill(ID2D1RenderTarget *target, ID2D1Brush *brush) const override;
      virtual Result draw(ID2D1RenderTarget *target, ID2D1Brush *brush, dtype stroke_width, ID2D1StrokeStyle *style) const override;
    protected:
      friend class D2DRender;
      D2DShapeRect(D2DRender *render);
      virtual ~D2DShapeRect();
  };
  class D2DShapeCircle : public ShapeCircle, public D2DShape {
    public:
      virtual Result fill(ID2D1RenderTarget *target, ID2D1Brush *brush) const override;
      virtual Result draw(ID2D1RenderTarget *target, ID2D1Brush *brush, dtype stroke_width, ID2D1StrokeStyle *style) const override;
    protected:
      friend class D2DRender;
      D2DShapeCircle(D2DRender *render);
      virtual ~D2DShapeCircle();
  };
  class D2DShapeEllipse : public ShapeEllipse, public D2DShape {
    public:
      virtual Result fill(ID2D1RenderTarget *target, ID2D1Brush *brush) const override;
      virtual Result draw(ID2D1RenderTarget *target, ID2D1Brush *brush, dtype stroke_width, ID2D1StrokeStyle *style) const override;
    protected:
      friend class D2DRender;
      D2DShapeEllipse(D2DRender *render);
      virtual ~D2DShapeEllipse();
  }; 

  class D2DShapePath : public ShapePath, public D2DShape {
    public:
      virtual Result fill(ID2D1RenderTarget *target, ID2D1Brush *brush) const override;
      virtual Result draw(ID2D1RenderTarget *target, ID2D1Brush *brush, dtype stroke_width, ID2D1StrokeStyle *style) const override;
    public:
      virtual Result reset() override;

      virtual Result open(const FillMode mode) override;
      virtual Result close() override;

      virtual Result begin_figure(const Point &start_point) override;
      virtual Result end_figure(const FigureEnd figure_end) override;

      virtual Result add_line(const Point &point) override;
      virtual Result add_lines(const Point *points, uint count) override;
      virtual Result add_bezier(const Point &pt1, const Point &pt2, const Point &pt3) override;
      virtual Result add_arc(const Point &point, const Size &size, dtype angle, bool sweep, bool large) override;

      virtual bool point_in_path(const Point &point) const override;
    public:
      Result create();
      ID2D1PathGeometry* d2d_path_geometry() const;
    protected:
      D2D1_FILL_MODE d2d_fill_mode(const FillMode mode) const;
      D2D1_FIGURE_END d2d_figure_end(const FigureEnd figure_end) const;
    protected:
      friend class D2DRender;
      D2DShapePath(D2DRender *render);
      virtual ~D2DShapePath();
    protected:
      ID2D1PathGeometry *d2d_path_;
      ID2D1GeometrySink *d2d_sink_;
  };

  class D2DShapeText : public ShapeText, virtual public D2DShape {
    public:
      virtual Result fill(ID2D1RenderTarget *target, ID2D1Brush *brush) const override;
      virtual Result draw(ID2D1RenderTarget *target, ID2D1Brush *brush, dtype stroke_width, ID2D1StrokeStyle *style) const override;
    public:
      virtual Result reset() override;
      virtual Result set(const wchar_t *text, uint len, const Rect &rect
          , const FontFormat &font, const TextFormat &format) override;
    protected:
      Result generate_dwrite_text_layout();
    protected:
      DWRITE_READING_DIRECTION get_reading_direction(TextDirection d) const;
      DWRITE_PARAGRAPH_ALIGNMENT get_align(TextAlignVer d) const;
      DWRITE_TEXT_ALIGNMENT get_align(TextAlignHor d) const;
    protected:
      friend class D2DRender;
      D2DShapeText(D2DRender *render);
      virtual ~D2DShapeText();
    protected:
      IDWriteTextLayout *dwrite_layout_;
      std::vector<ID2D1TransformedGeometry*> texts_;
      std::vector<ID2D1TransformedGeometry*> underlines_;
      std::vector<ID2D1TransformedGeometry*> strikethroughs_;
  };

  class D2DStrokeStyle : public D2DResource, virtual public IStrokeStyle {
    public:
      virtual Result reset() override;
      virtual LineCap start_line_cap() const override;
      virtual LineCap end_line_cap() const override;
      virtual LineCap dash_line_cap() const override;
      virtual LineJoin line_join() const override;
      virtual dtype miterlimit() const override;
      virtual dtype dash_offset() const override;
      virtual uint dashes_count() const override;
      virtual Result dashes_data(dtype *dashes, uint count) const override;
    public:
      Result create(const StrokeStyleProperties &props, const dtype *dashs, uint count);
      ID2D1StrokeStyle* d2d_stroke_style() const;
    protected:
      D2D1_CAP_STYLE d2d_cap_style(LineCap cap) const;
      D2D1_LINE_JOIN d2d_line_join(LineJoin join) const;
      LineCap cap_style(D2D1_CAP_STYLE cap) const;
      LineJoin line_join(D2D1_LINE_JOIN join) const; 
    protected:
      friend class D2DRender;
      D2DStrokeStyle(D2DRender *render);
      virtual ~D2DStrokeStyle();
    protected:
      ID2D1StrokeStyle *d2d_stroke_style_;
  };

  class D2DBrush : public D2DTargetResource, virtual public IBrush {
    public:
      virtual dtype opacity() const override;
      virtual Result set_opacity(dtype _opacity) override;
      virtual Matrix transform() const override;
      virtual Result set_transform(const Matrix &matrix) override;
    public:
      virtual ID2D1Brush* d2d_brush() const = 0;
    protected:
      D2DBrush(D2DRender *render, D2DTarget *target);
      virtual ~D2DBrush();
  };

  class D2DSolidColorBrush : public D2DBrush, virtual public ISolidColorBrush {
    public:
      virtual Result reset() override;
      virtual Color color() const override;
      virtual Result set_color(const Color &color) override;
    public:
      virtual ID2D1Brush* d2d_brush() const override;
    protected:
      friend class D2DTarget;
      D2DSolidColorBrush(D2DRender *render, D2DTarget *target);
      virtual ~D2DSolidColorBrush();
    public:
      Result create(const Color &color);
    protected:
      ID2D1SolidColorBrush *d2d_brush_;
  };

  class D2DGradientStopCollection : public D2DTargetResource, virtual public IGradientStopCollection {
    public:
      virtual Result reset() override;
      virtual uint count() const override;
      virtual Result data(GradientStop *stops) const override;
      virtual ExtendMode extend_mode() const override;
    public:
      Result create(const GradientStop *stops, uint count, ExtendMode mode);
      ID2D1GradientStopCollection* d2d_stop_collection() const;
    protected:
      friend class D2DTarget;
      D2DGradientStopCollection(D2DRender *render, D2DTarget *target);
      virtual ~D2DGradientStopCollection();
    protected:
      D2D1_EXTEND_MODE get_extend_mode(ExtendMode mode) const;
      ExtendMode get_extend_mode(D2D1_EXTEND_MODE mode) const;
    protected:
      ID2D1GradientStopCollection *d2d_stop_collection_;
  };
  class D2DLinearGradientBrush : public D2DBrush, virtual public ILinearGradientBrush {
    public:
      virtual Result reset() override;
      virtual IGradientStopCollection* stop_collection() const override;
      virtual Point start_point() const override;
      virtual Result set_start_point(const Point& point) override;
      virtual Point end_point() const override;
      virtual Result set_end_point(const Point& point) override;
    public:
      virtual ID2D1Brush* d2d_brush() const override;
    public:
      Result create(const LinearGradientBrushProperties &props, D2DGradientStopCollection *stop_collection);
    protected:
      friend class D2DTarget;
      D2DLinearGradientBrush(D2DRender *render, D2DTarget *target);
      virtual ~D2DLinearGradientBrush();
    protected:
      ID2D1LinearGradientBrush *d2d_brush_;
      D2DGradientStopCollection *stop_collection_;
  };
  class D2DRadialGradientBrush : public D2DBrush, virtual public IRadialGradientBrush {
    public:
      virtual Result reset() override;
      virtual IGradientStopCollection* stop_collection() const override;
      virtual Point center() const override;
      virtual Result set_center(const Point& center) override;
      virtual Point offset() const override;
      virtual Result set_offset(const Point& offset) override;
      virtual dtype radius_x() const override;
      virtual Result set_radius_x(dtype radius_x) override;
      virtual dtype radius_y() const override;
      virtual Result set_radius_y(dtype radius_y) override;
    public:
      virtual ID2D1Brush* d2d_brush() const override;
    public:
      Result create(const RadialGradientBrushProperties &props, D2DGradientStopCollection *stop_collection);
    protected:
      friend class D2DTarget;
      D2DRadialGradientBrush(D2DRender *render, D2DTarget *target);
      virtual ~D2DRadialGradientBrush();
    protected:
      ID2D1RadialGradientBrush *d2d_brush_;
      D2DGradientStopCollection *stop_collection_;
  };

  class D2DBitmap : public D2DTargetResource, virtual public IBitmap {
    public:
      virtual Result reset() override;
      virtual Result create(ISurface *surface) override;
      virtual Size size() const override;
    public:
      Result create(ID2D1Bitmap *bitmap);
      ID2D1Bitmap* d2d_bitmap() const;
    protected:
      friend class D2DTarget;
      friend class D2DBitmapTarget;
      D2DBitmap(D2DRender *render, D2DTarget *target);
      virtual ~D2DBitmap();
    protected:
      ID2D1Bitmap *d2d_bitmap_;
  };

  class D2DBitmapBrush : public D2DBrush, virtual public IBitmapBrush {
    public:
      virtual Result reset() override;
      virtual Result bitmap(IBitmap **_bitmap) const override;
      virtual Result set_bitmap(IBitmap *_bitmap) override;
      virtual ExtendMode extend_mode_x() const override;
      virtual ExtendMode extend_mode_y() const override;
      virtual Result set_extend_mode_x(ExtendMode mode_x) override;
      virtual Result set_extend_mode_y(ExtendMode mode_y) override;
    public:
      virtual ID2D1Brush* d2d_brush() const override;
    protected:
      friend class D2DTarget;
      D2DBitmapBrush(D2DRender *render, D2DTarget *target);
      virtual ~D2DBitmapBrush();
    protected:
      ExtendMode get_extend_mode(D2D1_EXTEND_MODE mode) const;
      D2D1_EXTEND_MODE get_extend_mode(ExtendMode mode) const;
    protected:
      ID2D1BitmapBrush *d2d_brush_;
      D2DBitmap *bitmap_;
  };

  class D2DTarget : public D2DResource, virtual public ITarget {
    public:
      virtual Matrix transform() const override;
      virtual Result set_transform(const Matrix &matrix) override;
      virtual Result begin_draw() override;
      virtual Result end_draw() override;
      virtual Result clear(const Color *color = 0) override;
      virtual Result fill_shape(IShape *shape, IBrush *brush) override;
      virtual Result draw_shape(IShape *shape, IBrush *brush, dtype stroke_width = 1.f, IStrokeStyle *stroke_style = 0) override;
      virtual Result draw_bitmap(IBitmap *bitmap, const Rect *dst = 0, const Rect *src = 0) override;
      virtual Result draw_bitmap(IBitmap *bitmap, const Point &pt, const Rect *src = 0) override;

      virtual Result create_compatible_target(IBitmapTarget **target) override;
      virtual Result create_bitmap(IBitmap **bitmap) override;
      virtual Result create_bitmap_brush(IBitmapBrush **brush) override;
      virtual Result create_solid_color_brush(const Color &color, ISolidColorBrush **brush) override;
      virtual Result create_linear_gradient_brush(const LinearGradientBrushProperties &props
          , IGradientStopCollection *stop_collection, ILinearGradientBrush **brush) override;
      virtual Result create_radial_gradient_brush(const RadialGradientBrushProperties &props
          , IGradientStopCollection *stop_collection, IRadialGradientBrush **brush) override;
      virtual Result create_gradient_stop_collection(const GradientStop *stops, uint count, ExtendMode mode
          , IGradientStopCollection **stop_ollection) override;
    public:
      virtual ID2D1RenderTarget* d2d_target() const = 0;
    protected:
      D2DTarget(D2DRender *render);
      virtual ~D2DTarget();
  };

  class D2DSurfaceTarget : public D2DTarget, virtual public ISurfaceTarget {
    public:
      virtual Result reset() override;
      virtual Result surface(ISurface **surface) const override;
    protected:
      friend class D2DRender;
      D2DSurfaceTarget(D2DRender *render);
      virtual ~D2DSurfaceTarget();
    public:
      virtual ID2D1RenderTarget* d2d_target() const override;
    public:
      Result create(const PixelFormat format, const Size &size);
    protected:
      D2DSurface *surface_;
      ID2D1RenderTarget *d2d_target_;
  };

  class D2DWindowTarget : public D2DTarget, virtual public IWindowTarget {
    public:
      virtual Result reset() override;
      virtual Result resize(Size size) override;
    protected:
      friend class D2DRender;
      D2DWindowTarget(D2DRender *render);
      virtual ~D2DWindowTarget();
    public:
      virtual ID2D1RenderTarget* d2d_target() const override;
    public:
      virtual Result create(void *handle, const Size &size);
    protected:
      ID2D1HwndRenderTarget *d2d_target_;
  };

  class D2DBitmapTarget : public D2DTarget, virtual public IBitmapTarget {
    public:
      virtual Result reset() override;
      virtual Result bitmap(IBitmap **_bitmap) override;
    protected:
      friend class D2DRender;
      D2DBitmapTarget(D2DRender *render);
      virtual ~D2DBitmapTarget();
    public:
      friend class D2DTarget;
      Result create(D2DTarget *target);
      virtual ID2D1RenderTarget* d2d_target() const override;
    protected:
      ID2D1BitmapRenderTarget *d2d_target_;
  };

  class D2DRender : public Base, virtual public IRender {
    public:
      virtual RenderType type() const override;
      virtual IFactory* factory() const override;
      virtual Result create_surface_target(const PixelFormat format, const Size &size, ISurfaceTarget **target) override;
      virtual Result create_window_target(void *handle, const Size &size, IWindowTarget **target) override;
      virtual Result create_shape_line(const Point &pt1, const Point &pt2, IShapeLine **shape) override;
      virtual Result create_shape_polyline(const Point *pts, uint count, IShapePolyline **shape) override;
      virtual Result create_shape_bezier(const BezierSegment &bezier, IShapeBezier **shape) override;
      virtual Result create_shape_arc(const ArcSegment &arc, IShapeArc **shape) override;
      virtual Result create_shape_polygon(const Point *pts, uint count, IShapePolygon **shape) override;
      virtual Result create_shape_rect(const Rect &rc, const Size &radius, IShapeRect **shape) override;
      virtual Result create_shape_circle(const Point &center, dtype radius, IShapeCircle **shape) override;
      virtual Result create_shape_ellipse(const Point &center, const Size &radius, IShapeEllipse **shape) override;
      virtual Result create_shape_path(IShapePath **shape) override;
      virtual Result create_shape_text(const wchar_t *text, uint len, const Rect &rect
          , const FontFormat &font, const TextFormat &format, IShapeText **shape) override;
      virtual Result create_stroke_style(const StrokeStyleProperties &props, const dtype *dashs, uint count
          , IStrokeStyle **stroke_style) override;
      virtual Result create_surface(ISurface **surface) override;
    protected:
      friend Result create_render(IFactory *factory, IRender **render);
      D2DRender(IFactory *factory);
      virtual ~D2DRender();
    public:
      Result reset();
      Result init();
      ID2D1Factory* d2d_factory() const;
      IDWriteFactory* dwrite_factory() const;
      CustomTextRender* text_render() const;
    public:
      static Result create_dl(IDynamicLibrary **dl, const char *name);
      static Result create_d2d_factory(IDynamicLibrary *dl, ID2D1Factory **factory);
      static Result create_dwrite_factory(IDynamicLibrary *dl, IDWriteFactory **factory);
      static bool is_supported();
    protected:
      IFactory *factory_;
      IDynamicLibrary *d2d_dl_;
      IDynamicLibrary *dwrite_dl_;
      ID2D1Factory *d2d_factory_;
      IDWriteFactory *dwrite_factory_;
      CustomTextRender *text_render_;
  };
} // end namespace c2d
} // end namespace cvs

#endif // __CANVAS_D2D_IMPL_H__